/***************************************************************************************************
  *Copyright(C),2010-2017,Sumscope
  *FileName	:  BitView.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2019/09/17
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#ifndef BITVIEW_H_B2927342_E6BF_463F_87A7_7D740475E9AB
#define BITVIEW_H_B2927342_E6BF_463F_87A7_7D740475E9AB
#include "../extdef.h"
namespace qb{
	namespace proto{
		class SSPROTOAPI BitView{
		protected://参数
			const unsigned char*		m_buf;			// 字符串指针
			int							m_capcity;		// 字符串字节长度
			int							m_bitwidth;		// 比特宽度,4,6,8
			bool						m_stop;			// 是否有停止位,有:解码,无:编码
		protected://计算值
			unsigned short				m_mask;			// 16bit的掩码,只取低m_bitwidth个bit位
			int							m_count;		// 单位个数
			int							m_char_bit;		// 一个字符容纳的bit位,有stop,为7,无则为8
		public:
			BitView(const unsigned char* buf, int capcity, int bitwidth, bool stop,bool complete) :
				m_buf(buf), m_capcity(capcity), m_bitwidth(bitwidth),
				m_mask((1 << bitwidth) - 1), m_stop(stop),
				m_char_bit(stop ? (CHAR_BIT - 1) : CHAR_BIT)
			{
				// 7bit特殊处理,不需要完成标志
				int bits = m_capcity*m_char_bit;
				if (complete && bitwidth != m_char_bit)
					bits -= 1;
				m_count = bits / m_bitwidth;
				if (complete && stop && bitwidth != m_char_bit && !(m_buf[m_capcity - 1] & CompleteFlag))
				{
					if (m_count*bitwidth - bitwidth >= (m_capcity - 1)*m_char_bit)
						m_count--;
				}
			}
			inline int size()const{ return m_count; }
			unsigned char at(int index)const
			{
				BASSERT(index >= 0 && index < m_count);
				int bitpos = index*m_bitwidth;			// 当前编码单位的总bit序号
				int pos = bitpos / m_char_bit;			// 当前字节的序号
				int start = bitpos - pos*m_char_bit;	// 当前字节的第几个bit开始
				int end = start + m_bitwidth;			// 当前编码单位的bit结束序号
				unsigned short code = raw(pos);			// 第pos个字节,移除停止位
				if (end > m_char_bit)
				{
					code |= ((unsigned short)raw(pos + 1)) << m_char_bit;
				}
				code = (code >> start)&m_mask;
				return (unsigned char)code;
			}
		protected:
			inline unsigned char raw(int index)const
			{
				return m_stop ? m_buf[index] & 0x7f : m_buf[index];
			}
		};

	}//namespace base;
}//namespace ss;



#endif
